﻿using Google.Protobuf.WellKnownTypes;
using Grpc.Core;
using Grpc.Core.Interceptors;
using Grpc.Net.Client;
using GrpcDemo;
using System;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;

namespace GrpcClient
{
    class Program
    {
        static async Task Main(string[] args)
        {

            //如果是http调用grpc 需要这一句
            AppContext.SetSwitch(
    "System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupport", true);
            var channel = GrpcChannel.ForAddress("http://localhost:5000");
            //var channel = GrpcChannel.ForAddress("https://localhost:5001");
            var client = new Greeter.GreeterClient(channel);
            var reply = await client.SayHelloAsync(
                new HelloRequest { Name = "晓晨" });
            Console.WriteLine("Greeter 服务返回数据: " + reply.Message);


            var headers = new Metadata { { "Authorization", $"username" } };

            var catClient = new LuCat.LuCatClient(channel);
            var catReply = await catClient.SuckingCatAsync(new Empty(), headers);
            Console.WriteLine("调用撸猫服务：" + catReply.Message);




            //获取猫总数
            var catCount = await catClient.CountAsync(new Empty());
            Console.WriteLine($"一共{catCount.Count}只猫。");
            var rand = new Random(DateTime.Now.Millisecond);

            var bathCat = catClient.BathTheCat();
            //定义接收吸猫响应逻辑
            var bathCatRespTask = Task.Run(async () =>
            {
                await foreach (var resp in bathCat.ResponseStream.ReadAllAsync())
                {
                    Console.WriteLine(resp.Message);
                }
            });
            //随机给10个猫洗澡
            for (int i = 0; i < 10; i++)
            {
                await bathCat.RequestStream.WriteAsync(new BathTheCatReq() { Id = rand.Next(0, catCount.Count) });
            }
            //发送完毕
            await bathCat.RequestStream.CompleteAsync();
            Console.WriteLine("客户端已发送完10个需要洗澡的猫id");
            Console.WriteLine("接收洗澡结果：");
            //开始接收响应
            await bathCatRespTask;

            Console.WriteLine("洗澡完毕");


            Console.WriteLine("再次洗澡，第五只猫取消：");
            var invoker = channel.Intercept(new ClientLoggerInterceptor());
            LuCat.LuCatClient catClient2 = new LuCat.LuCatClient(invoker);

            var catReply2 = await catClient2.SuckingCatAsync(new Empty());
            Console.WriteLine("调用撸猫服务2（拦截）：" + catReply2.Message);


            var cts = new CancellationTokenSource();
            //指定在5s后进行取消操作
            cts.CancelAfter(TimeSpan.FromSeconds(5));
            var bathCat2 = catClient.BathTheCat(cancellationToken:cts.Token);
            //定义接收吸猫响应逻辑
            var bathCatRespTask2 = Task.Run(async () =>
            {
                try
                {
                    int index = 0;
                    await foreach (var resp in bathCat2.ResponseStream.ReadAllAsync())
                    {
                        if (++index==2)
                        {
                            cts.Cancel();//调用cancel 客户端主动取消
                        }
                        Console.WriteLine(resp.Message);
                    }
                }catch(RpcException ex) when (ex.StatusCode == StatusCode.Cancelled)
                {
                    Console.WriteLine("Stream cancelled.");
                }
            });
            //随机给10个猫洗澡
            for (int i = 0; i < 10; i++)
            {
                await bathCat2.RequestStream.WriteAsync(new BathTheCatReq() { Id = rand.Next(0, catCount.Count) });
            }
            //发送完毕
            await bathCat2.RequestStream.CompleteAsync();
            Console.WriteLine("客户端已发送完2个需要洗澡的猫id");
            Console.WriteLine("接收洗澡结果：");
            //开始接收响应
            await bathCatRespTask2;

            Console.WriteLine("洗澡完毕");





            Console.WriteLine("鉴权调用");

            Console.ReadKey();
        }
    }
}
